/*
 * @Author: silence
 * @Date: 2022-07-16 11:04:32
 * @LastEditors: silence silence9685@163.com
 * @LastEditTime: 2023-07-26 15:26:19
 * @Description: 网络缓存拦截器：处理添加接口数据缓存
 */
import 'package:dio/dio.dart';
import 'package:sil_utils_package/sil_utils_package.dart';

import '../utils/category/string+utis.dart';
import 'NetCacheManager.dart';

/**
 * 如何使用：
 * 1.将需要缓存的接口名称，放入needCacheApiList数组中
 * 2.处理缓存的key(方法hanndlerCacheKey中),考虑接口相同的情况，可以根据分类id进行区分
 * 3.手动清理缓存：需要在请求扩展参数extra中，添加一个参数'cleanCache'
 */

/**1.记录需要缓存的接口*/
List needCacheApiList = [
  '/api/v1.arcade/common/category_apps',
  '/api/v1.arcade/common/ngds'
];

/**记录启动之后自动刷新了列表*/
List appLunchRefreshList = [];

class NetCacheInterceptor extends Interceptor {
  ///2. 处理缓存的key值，默认key为接口名称
  String hanndlerCacheKey(String urlPath, Map<String, dynamic>? tempParam) {
    String tempKey = urlPath;
    // 考虑接口相同的情况，添加参数进行区分，比如列表需要区分类别、分类id等
    if (!SilTools.mapIsEmpty(tempParam)) {
      // 去除时间戳、page、签名参数，因为每次都不同
      Map<String, dynamic> tempMap = Map();
      tempParam!.forEach((key, value) {
        if ([
              'page',
              'timestamp',
              'sign',
            ].contains(key) ==
            false) {
          tempMap[key] = value;
        }
      });

      if (!SilTools.mapIsEmpty(tempMap)) {
        tempKey = urlPath + "&" + StringUtils.generateMD5(tempMap.toString());
      }
    }
    return tempKey;
  }

  /// 拦截请求，返回缓存数据
  void onRequest(
    RequestOptions options,
    RequestInterceptorHandler handler,
  ) {
    String urlPath = options.path; // 接口（不包括baseUrl）
    // 需要缓存的接口，才能获取缓存数据
    if (needCacheApiList.contains(urlPath)) {
      Map<String, dynamic>? postBodyParam = options.data; //post body接口参数
      Map<String, dynamic>? getBodyParm = options.queryParameters; //get body参数

      Map<String, dynamic> tempParam = Map(); // 接口参数
      if (!SilTools.mapIsEmpty(getBodyParm)) tempParam.addAll(getBodyParm);
      if (!SilTools.mapIsEmpty(postBodyParam)) tempParam.addAll(postBodyParam!);

      String tempKey = hanndlerCacheKey(urlPath, tempParam);

      // 是否需要清理缓存
      // 1 用户手动刷新，需要清空缓存，获取新数据
      bool isNeedCleanCache = false;
      if (options.extra.containsKey('cleanCache')) {
        isNeedCleanCache = options.extra['cleanCache'];
      }

      // 2 qpp启动时，需要清空缓存，获取新数据
      if (appLunchRefreshList.contains(tempKey) == false) {
        isNeedCleanCache = true;
      }

      // 是否清掉缓存
      if (isNeedCleanCache) {
        NetCacheManager().cleanCache(tempKey);
        SilLog.e('------------------清空,key为$tempKey的缓存数据--------------');
      } else {
        int page = 1;
        if (!SilTools.mapIsEmpty(tempParam)) {
          if (tempParam.containsKey('page')) {
            page = tempParam['page'];
          }
        }
        List pageList = NetCacheManager().getCacheData(tempKey, page, 1);

        if (!SilTools.listIsEmpty(pageList)) {
          // 有缓存，直接返回
          Map<String, dynamic> responseData = {
            'code': 0,
            'msg': '成功',
            'data': pageList.first
          };
          handler
              .resolve(Response(data: responseData, requestOptions: options));
          return;
        }
      }
    }

    handler.next(options);
  }

  /// 请求响应，获取保存缓存数据
  void onResponse(
    Response response,
    ResponseInterceptorHandler handler,
  ) {
    RequestOptions options = response.requestOptions;
    String urlPath = response.requestOptions.path; // 接口（不包括baseUrl）

    // 需要缓存的接口，才进行缓存数据
    if (needCacheApiList.contains(urlPath)) {
      Map<String, dynamic>? postBodyParam = options.data; //post body接口参数
      Map<String, dynamic>? getBodyParm = options.queryParameters; //get body参数

      Map<String, dynamic> tempParam = Map(); // 接口参数
      if (!SilTools.mapIsEmpty(getBodyParm)) tempParam.addAll(getBodyParm);
      if (!SilTools.mapIsEmpty(postBodyParam)) tempParam.addAll(postBodyParam!);
      String tempKey = hanndlerCacheKey(urlPath, tempParam);

      NetCacheManager().saveCacheData(tempKey, response).then((value) {
        // 保存第一次启动时，缓存数据的记录
        if (!appLunchRefreshList.contains(tempKey))
          appLunchRefreshList.add(tempKey);
      });
    }

    handler.next(response);
  }

  void onError(
    DioError err,
    ErrorInterceptorHandler handler,
  ) {
    SilLog.e('DioError:$err,ErrorInterceptorHandler:$handler');

    handler.next(err);
  }
}
